package orbitPrototype.gui;

import java.awt.Color;

import orbitPrototype.Util;
import orbitPrototype.loaders.XMLLoader;
import orbitPrototype.objects.RectangleShape;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Description:	Base class for GUI containers such GUIWindow and GUITab. Created from base
 * 				XMLElement which contains all its subelements.
 * 
 * @author Drapan
 *
 */
public class GUIXMLContainer extends GUIElement
{		
	private GUIStyle _style = null;
		
	public GUIXMLContainer(int x, int y, int width, int height, Element xmlElement, GUIWindow parentWindow)
	{
		super(x, y, width, height, parentWindow);
		
		_style = new GUIStyle(XMLLoader.getElementValue("style", xmlElement));
		
		addLabels(xmlElement);
		addButtons(xmlElement);
		addTabControllers(xmlElement);
	}
		
	/**
	 * Description:	Adds all objects under <labels> subtag to this GUIWindow
	 * @param xmlElement
	 */
	private void addLabels(Element xmlElement)
	{
		NodeList labelList = xmlElement.getElementsByTagName("labels").item(0).getChildNodes();
		for(int i = 0; i < labelList.getLength(); i++)
		{
			if(labelList.item(i).getNodeType() == Node.ELEMENT_NODE)
			{
				Element label = (Element) labelList.item(i);
				
				if(label.getTagName().equals(Util.getClassNameOnly(GUIText.class)))
				{
					this.addChild(constructLabelFromElement(label));
				}
				else
				{
					Util.error("Unknown label element " + label.getTagName() + " in " + this.getParentWindow().getWindowName());
				}
			}	
		}
	}
	
	/**
	 * Description:	Adds all objects under <buttons> subtag to this GUIWindow
	 * @param xmlElement
	 * @param actionGlobal
	 */
	private void addButtons(Element xmlElement)
	{
		NodeList buttonList = xmlElement.getElementsByTagName("buttons").item(0).getChildNodes();
		for(int i = 0; i < buttonList.getLength(); i++)
		{
			if(buttonList.item(i).getNodeType() == Node.ELEMENT_NODE)
			{
				Element button = (Element) buttonList.item(i);
				
				if(button.getTagName().equals(Util.getClassNameOnly(GUISpriteButton.class)))
				{
					this.addChild(constructSpriteButtonFromElement(button));
				}
				else if(button.getTagName().equals(Util.getClassNameOnly(GUIComplexButton.class)))
				{
					this.addChild(constructComplexButtonFromElement(button));
				}
				else
				{
					Util.error("Unknown button element " + button.getTagName() + " in " + this.getParentWindow().getWindowName());
				}
			}	
		}
	}
	
	private void addTabControllers(Element xmlElement)
	{
		// Tab controllers currently not supported within tab controllers
		if(!xmlElement.getTagName().equals(Util.getClassNameOnly(GUITab.class)))
		{
			NodeList tabControllerList = xmlElement.getElementsByTagName("tabControllers").item(0).getChildNodes();
			for(int i = 0; i < tabControllerList.getLength(); i++)
			{
				if(tabControllerList.item(i).getNodeType() == Node.ELEMENT_NODE)
				{
					Element tabController = (Element) tabControllerList.item(i);
										
					if(tabController.getTagName().equals(Util.getClassNameOnly(GUITabControl.class)))
					{
						this.addChild(constructTabControlFromElement(tabController));
					}
					else
					{
						Util.error("Unknown tab element " + tabController.getTagName() + " in " + this.getParentWindow().getWindowName());
					}
				}
			}
		}
		
	}
	
	/**
	 * Description:	Adds all objects under <shapes> subtag to this GUIWindow
	 * @param xmlElement
	 */
	private void addShapes(Element xmlElement)
	{
		NodeList shapeList = xmlElement.getElementsByTagName("shapes").item(0).getChildNodes();		
		for(int i = 0; i < shapeList.getLength(); i++)
		{
			if(shapeList.item(i).getNodeType() == Node.ELEMENT_NODE)
			{
				Element shape = (Element) shapeList.item(i);

				this.addChild(constructRectangleShapeFromElement(shape));
			}	
		}
	}
	
	/**
	 * Description:	Constructs GUIText from XMLElement
	 * @param xmlElement
	 * @return
	 */
	private GUIText constructLabelFromElement(Element xmlElement)
	{
		int x = getElementCoordValue("x", xmlElement, this.getWidth());
		int y = getElementCoordValue("y", xmlElement, this.getHeight());
		String text = XMLLoader.getElementValue("text", xmlElement);
		String font = XMLLoader.getElementValue("font", xmlElement);
		String adjustment = XMLLoader.getElementValue("adjustment", xmlElement);
		
		if(!font.equals("") && !adjustment.equals(""))
		{
			return new GUIText(x, y, text, adjustment, font, this.getParentWindow());
		}
		if(font.equals("") && !adjustment.equals(""))
		{
			return new GUIText(x, y, text, adjustment, GUIText.DEFAULT_FONT, this.getParentWindow());
		}
		if(!font.equals("") && adjustment.equals(""))
		{
			return new GUIText(x, y, text, GUIText.DEFAULT_ADJUSTMENT, font, this.getParentWindow());
		}
		else
		{
			return new GUIText(x, y, text, GUIText.DEFAULT_ADJUSTMENT, GUIText.DEFAULT_FONT, this.getParentWindow());
		}
	}
	
	/**
	 * Description:	Constructs GUIComplexButton from XMLElement
	 * @param xmlElement
	 * @return
	 */
	private GUIComplexButton constructComplexButtonFromElement(Element xmlElement)
	{
		int x = getElementCoordValue("x", xmlElement, this.getWidth());
		int y = getElementCoordValue("y", xmlElement, this.getHeight());
		int width = getElementSizeValue("width", xmlElement, this.getWidth());
		int height = getElementSizeValue("height", xmlElement, this.getHeight());
		String actionLabel = XMLLoader.getElementValue("actionLabel", xmlElement);
		String textLabel = XMLLoader.getElementValue("textLabel", xmlElement);
		String style = XMLLoader.getElementValue("style", xmlElement);
		
		if(style.equals(""))
		{
			return new GUIComplexButton(x, y, width, height, this.getParentWindow(), actionLabel, null, textLabel, this.getStyle());
		}
		else
		{
			return new GUIComplexButton(x, y, width, height, this.getParentWindow(), actionLabel, null, textLabel, new GUIStyle(style));
		}	
	}
	
	/**
	 * Description:	Constructs GUISpriteButton from XMLElement
	 * @param xmlElement
	 * @return
	 */
	private GUISpriteButton constructSpriteButtonFromElement(Element xmlElement)
	{
		int x = getElementCoordValue("x", xmlElement, this.getWidth());
		int y = getElementCoordValue("y", xmlElement, this.getHeight());
		String actionLabel = XMLLoader.getElementValue("actionLabel", xmlElement);
		String spriteUniqueName = XMLLoader.getElementValue("spriteUniqueName", xmlElement);
		boolean hover = XMLLoader.getElementBooleanValue("hover", xmlElement);
		boolean down = XMLLoader.getElementBooleanValue("down", xmlElement);
		
		return new GUISpriteButton(x, y, actionLabel, null, spriteUniqueName, hover, down, this.getParentWindow());
	}
	
	/**
	 * Description:	Constructs GUITabControl from XMLElement
	 * @param xmlElement
	 * @return
	 */
	private GUITabControl constructTabControlFromElement(Element xmlElement)
	{
		Util.output("Tagname: " + xmlElement.getTagName()); 
		
		int x = getElementCoordValue("x", xmlElement, this.getWidth());
		int y = getElementCoordValue("y", xmlElement, this.getHeight());
		int width = getElementSizeValue("width", xmlElement, this.getWidth());
		int height = getElementSizeValue("height", xmlElement, this.getHeight());
		
		NodeList tabNodes = xmlElement.getElementsByTagName(Util.getClassNameOnly(GUITab.class));
		GUITab[] tabs = new GUITab[tabNodes.getLength()];
		
		GUITabControl controller = new GUITabControl(x, y, width, height, this.getParentWindow());
		
		for(int i = 0; i < tabs.length; i++)
		{
			Element tabElement = (Element) tabNodes.item(i);
			
			tabs[i] = new GUITab(0, 0, width, height - GUITabControl.CONTENT_Y, tabElement, controller, this.getParentWindow());
		}
		
		controller.addTabs(tabs);
		
		return controller;
	}
	
	/**
	 * Description:	Constructs RectangleShape from XMLElement
	 * @param xmlElement
	 * @return
	 */
	private RectangleShape constructRectangleShapeFromElement(Element xmlElement)
	{
		int x = getElementCoordValue("x", xmlElement, this.getWidth());
		int y = getElementCoordValue("y", xmlElement, this.getHeight());
		int width = getElementSizeValue("width", xmlElement, this.getWidth());
		int height = getElementSizeValue("height", xmlElement, this.getHeight());
		int color = Integer.parseInt(XMLLoader.getElementValue("color", xmlElement));
		
		return new RectangleShape(x, y, width, height, new Color(color));
	}
	
	/**
	 * Description:	Gets coordinates, if necessary converts from px and mx to absolute x
	 * @param tag
	 * @param xmlElement
	 * @param total
	 * @return
	 */
	private int getElementCoordValue(String tag, Element xmlElement, int total)
	{
		if(XMLLoader.getElementValue(tag, xmlElement).equals(""))
		{
			if(XMLLoader.getElementValue("p" + tag, xmlElement).equals(""))
			{
				return total - Integer.parseInt(XMLLoader.getElementValue("m" + tag, xmlElement));
			}
			else
			{
				return ((Integer.parseInt(XMLLoader.getElementValue("p" + tag, xmlElement)) * total) / 100);
			}	
		}
		else
		{
			return Integer.parseInt(XMLLoader.getElementValue(tag, xmlElement));
		}
	}
	
	/**
	 * Description:	Gets size, converts percentage to x/y if needed.
	 * @param tag
	 * @param xmlElement
	 * @param total
	 * @return
	 */
	private int getElementSizeValue(String tag, Element xmlElement, int total)
	{
		if(XMLLoader.getElementValue(tag, xmlElement).equals(""))
		{
			if(XMLLoader.getElementValue("p" + tag, xmlElement).equals(""))
			{
				return 0;
			}
			else
			{
				return ((Integer.parseInt(XMLLoader.getElementValue("p" + tag, xmlElement)) * total) / 100);
			}	
		}
		else
		{
			return Integer.parseInt(XMLLoader.getElementValue(tag, xmlElement));
		}
	}
	
	public GUIStyle getStyle()
	{
		return _style;
	}
}
